﻿using System;
using System.Collections.Generic;
 
using System.Text;
using System.Runtime.InteropServices;


namespace HDF5
{
    using hid_t = System.Int32;
    using herr_t = System.Int32;
    using hsize_t = System.UInt64;
    using hssize_t = System.Int64;
    using hunsigned = System.UInt32;

    using hbool_t = System.UInt32;
    using htri_t = System.Int32;
    using ssize_t = System.Int64;

    using haddr_t = System.UInt64;

    using uint32_t = System.UInt32;
    using uint64_t = System.UInt64;

    using H5O_msg_crt_idx_t = System.UInt32;

    using size_t = System.UInt32;

    using off_t = System.Int32;

    using H5E_major_t = System.Int32;
    using H5E_minor_t = System.Int32;


    #region enums
    /* Different kinds of error information */
    public enum H5E_type_t {
        H5E_MAJOR,
        H5E_MINOR
    } 

    /* Error stack traversal direction */
    public enum H5E_direction_t {
        H5E_WALK_UPWARD	= 0,		/*begin deep, end at API function    */
        H5E_WALK_DOWNWARD	= 1		/*begin at API function, end deep    */
    }
    #endregion enums


    #region structs
    /* Information about an error; element of error stack */
    [StructLayout(LayoutKind.Sequential)]
    public struct H5E_error2_t {
        hid_t       cls_id;         /*class ID                           */
        hid_t       maj_num;	/*major error ID		     */
        hid_t       min_num;	/*minor error number		     */
        hunsigned	line;		/*line in file where error occurs    */
        [MarshalAs(UnmanagedType.LPStr)]string func_name;   	/*function in which error occurred   */
        [MarshalAs(UnmanagedType.LPStr)]string file_name;	/*file in which error occurred       */
        [MarshalAs(UnmanagedType.LPStr)]string desc;		/*optional supplied description      */
    }  

        /* Information about an error element of error stack. */
    public struct H5E_error1_t {
        H5E_major_t maj_num;                /*major error number                 */
        H5E_minor_t min_num;                /*minor error number                 */
        [MarshalAs(UnmanagedType.LPStr)]string func_name;             /*function in which error occurred   */
        [MarshalAs(UnmanagedType.LPStr)]string file_name;             /*file in which error occurred       */
        hunsigned    line;                   /*line in file where error occurs    */
        [MarshalAs(UnmanagedType.LPStr)]string desc;                  /*optional supplied description      */
    }
    #endregion structs

    #region delegates
    /* Error stack traversal callback function pointers */
    delegate herr_t H5E_walk2_t(hunsigned n, ref H5E_error2_t err_desc,IntPtr client_data);
    delegate herr_t H5E_auto2_t(hid_t estack, IntPtr client_data);
    
    /* Error stack traversal callback function pointers */
    delegate herr_t H5E_walk1_t(int n, ref H5E_error1_t err_desc, IntPtr client_data);
    delegate herr_t H5E_auto1_t(IntPtr client_data);

    #endregion delegates

    public static class H5E
    {
        public static int H5E_DEFAULT = 0;
        public static hid_t H5E_ERR_CLS;

        static H5E()
        {
            int status = H5.H5open();
            IntPtr hdl = LoadLibrary("hdf5dll.dll");
            if (hdl == IntPtr.Zero)
            {
                throw new Exception("Failed to load hdf5dll.dll dll library!");
            }
            H5E_ERR_CLS = Marshal.ReadInt32(GetProcAddress(hdl, "H5E_ERR_CLS_g"));
            bool isFreed = FreeLibrary(hdl);
        }

        #region Error Interface
        [DllImport("hdf5dll.dll",CharSet=CharSet.Ansi)]
        public static extern herr_t H5Eclear1( ) ;

        [DllImport("hdf5dll.dll",CharSet=CharSet.Ansi)]
        public static extern herr_t H5Eclear2( hid_t estack_id ) ;

        [DllImport("hdf5dll.dll",CharSet=CharSet.Ansi)]
        public static extern hid_t H5Ecreate_stack() ;

        [DllImport("hdf5dll.dll",CharSet=CharSet.Ansi)]
        public static extern herr_t H5Eclose_stack(hid_t estack_id) ;

        //[DllImport("hdf5dll.dll",CharSet=CharSet.Ansi)]
        //public static extern herr_t H5Eprint1( FILE * stream ) ;

        //[DllImport("hdf5dll.dll",CharSet=CharSet.Ansi)]
        //public static extern herr_t H5Eprint2( hid_t estack_id, FILE * stream) ;

        [DllImport("hdf5dll.dll",CharSet=CharSet.Ansi)]
        public static extern herr_t H5Epush( [In][MarshalAs(UnmanagedType.LPStr)] string file, [In][MarshalAs(UnmanagedType.LPStr)] string func, hunsigned line, H5E_major_t maj_num, H5E_minor_t min_num, [In][MarshalAs(UnmanagedType.LPStr)] string str ) ;

        //[DllImport("hdf5dll.dll", CharSet = CharSet.Ansi)]
        //public static extern herr_t H5Epush([In][MarshalAs(UnmanagedType.LPStr)] string file, [In][MarshalAs(UnmanagedType.LPStr)] string func, hunsigned line, H5E_major_t maj_num, H5E_minor_t min_num, [In][MarshalAs(UnmanagedType.LPStr)] string str);

        //[DllImport("hdf5dll.dll",CharSet=CharSet.Ansi)]
        //public static extern herr_t H5Epush2( hid_t estack_id, const char *file, const char *func, unsigned line, hid_t class_id, hid_t major_id, hid_t minor_id, const char *msg, ...) ;

        [DllImport("hdf5dll.dll",CharSet=CharSet.Ansi)]
        public static extern herr_t H5Epop(hid_t estack_id, size_t count)  ;

        [DllImport("hdf5dll.dll",CharSet=CharSet.Ansi)]
        public static extern ssize_t H5Eget_num(hid_t estack_id) ;

        [DllImport("hdf5dll.dll",CharSet=CharSet.Ansi)]
        public static extern ssize_t H5Eget_msg(hid_t mesg_id, out H5E_type_t mesg_type, StringBuilder mesg, size_t size) ;

        [DllImport("hdf5dll.dll",CharSet=CharSet.Ansi)]
        public static extern hid_t H5Ecreate_msg(hid_t classId, H5E_type_t msg_type, [In][MarshalAs(UnmanagedType.LPStr)] string mesg) ;

        [DllImport("hdf5dll.dll",CharSet=CharSet.Ansi)]
        public static extern herr_t H5Eclose_msg(hid_t mesg_id)  ;

        [DllImport("hdf5dll.dll",CharSet=CharSet.Ansi)]
        public static extern hid_t H5Eregister_class([In][MarshalAs(UnmanagedType.LPStr)] string cls_name, [In][MarshalAs(UnmanagedType.LPStr)] string lib_name, [In][MarshalAs(UnmanagedType.LPStr)] string version) ;

        [DllImport("hdf5dll.dll",CharSet=CharSet.Ansi)]
        public static extern herr_t H5Eunregister_class(hid_t class_id) ;

        [DllImport("hdf5dll.dll",CharSet=CharSet.Ansi)]
        public static extern ssize_t H5Eget_class_name(hid_t class_id, StringBuilder name, size_t size) ;

        [DllImport("hdf5dll.dll",CharSet=CharSet.Ansi)]
        public static extern herr_t H5Eauto_is_v2( hid_t estack_id, out hunsigned is_stack ) ;

        //[DllImport("hdf5dll.dll",CharSet=CharSet.Ansi)]
        //public static extern herr_t H5Eset_auto( H5E_auto_t func, void *client_data ) ;

        //[DllImport("hdf5dll.dll",CharSet=CharSet.Ansi)]
        //public static extern herr_t H5Eset_auto( hid_t estack_id, H5E_auto_t func, IntPtr client_data ) ;

        //[DllImport("hdf5dll.dll",CharSet=CharSet.Ansi)]
        //public static extern herr_t H5Eset_auto2( hid_t estack_id, H5E_auto2_t func, IntPtr client_data ) ;

        //[DllImport("hdf5dll.dll",CharSet=CharSet.Ansi)]
        //public static extern herr_t H5Eget_auto( H5E_auto_t * func, void **client_data ) ;

        //[DllImport("hdf5dll.dll",CharSet=CharSet.Ansi)]
        //public static extern herr_t H5Eget_auto( hid_t estack_id, H5E_auto_t * func, void **client_data ) ;

        //[DllImport("hdf5dll.dll",CharSet=CharSet.Ansi)]
        //public static extern herr_t H5Eget_auto2(hid_t estack_id, H5E_auto2_t* func, void** client_data);

        //[DllImport("hdf5dll.dll",CharSet=CharSet.Ansi)]
        //public static extern herr_t H5Ewalk( H5E_direction_t direction, H5E_walk_t func, void * client_data ) ;

        //[DllImport("hdf5dll.dll",CharSet=CharSet.Ansi)]
        //public static extern herr_t H5Ewalk( hid_t estack_id, H5E_direction_t direction, H5E_walk_t func, void * client_data ) ;

        //[DllImport("hdf5dll.dll",CharSet=CharSet.Ansi)]
        //public static extern herr_t H5Ewalk2( hid_t estack_id, H5E_direction_t direction, H5E_walk2_t func, void * client_data ) ;

        [DllImport("hdf5dll.dll",CharSet=CharSet.Ansi)]
        public static extern hid_t H5Eget_current_stack() ;

        [DllImport("hdf5dll.dll",CharSet=CharSet.Ansi)]
        public static extern herr_t H5Eset_current_stack(hid_t estack_id);


        #endregion Error Interface

        #region kernel32 functions
        [DllImport("kernel32.dll", SetLastError = true)]
        private static extern IntPtr GetProcAddress(IntPtr hModule, string procName);

        [DllImport("kernel32.dll", SetLastError = true)]
        private static extern IntPtr LoadLibrary(string lpszLib);

        [DllImport("kernel32", SetLastError = true)]
        private static extern bool FreeLibrary(IntPtr handle);
        #endregion kernel32 functions


    }
}
